Drought · Soil & Vegetation Moisture

NMDI – Normalized Multi-band Drought Index

NMDI is a multi-band drought index that combines NIR and two SWIR bands to estimate vegetation and soil moisture, and to monitor agricultural and hydrological drought.

1. Scientific Definition

The Normalized Multi-band Drought Index (NMDI) exploits the strong sensitivity of SWIR bands to liquid water in leaves and soil, combined with NIR reflectance, to track moisture stress.

Formula

NMDI = (NIR − (SWIR1 − SWIR2)) / (NIR + (SWIR1 − SWIR2))

  • NIR – Near Infrared reflectance
  • SWIR1 – first SWIR band (shorter wavelength)
  • SWIR2 – second SWIR band (longer wavelength)

Interpretation

  • High NMDI → higher moisture content (wetter vegetation & soil)
  • Low / negative NMDI → drier conditions / drought stress

Applications

  • Agricultural and ecological drought monitoring
  • Soil and canopy water content mapping
  • Early warning of vegetation stress

2. Required Bands

Sentinel-2

  • NIR → B8 (~842 nm)
  • SWIR1 → B11 (~1610 nm)
  • SWIR2 → B12 (~2190 nm)

Landsat 8/9 (equivalent)

  • NIR → B5
  • SWIR1 → B6
  • SWIR2 → B7

Suggested Palette

[ "#7f0000", "#d73027", "#fdae61", "#ffffbf", "#a6d96a", "#1a9850" ]

3. Google Earth Engine Code – NMDI (Sentinel-2)


// NMDI – Normalized Multi-band Drought Index
// NMDI = (NIR - (SWIR1 - SWIR2)) / (NIR + (SWIR1 - SWIR2))

var roi = geometry;
Map.centerObject(roi, 8);

// 1. Load Sentinel-2 SR
var s2 = ee.ImageCollection("COPERNICUS/S2_SR")
  .filterBounds(roi)
  .filterDate("2023-01-01", "2023-12-31")
  .filter(ee.Filter.lt("CLOUDY_PIXEL_PERCENTAGE", 30))
  .select(["B8","B11","B12"]); // NIR, SWIR1, SWIR2

var img = s2.median().clip(roi);

// 2. Compute (SWIR1 - SWIR2)
var swirDiff = img.select("B11").subtract(img.select("B12")).rename("SWIR1_minus_SWIR2");

// 3. Compute NMDI
var nmdi = img.expression(
  "(NIR - (S1 - S2)) / (NIR + (S1 - S2))",
  {
    "NIR": img.select("B8"),
    "S1": img.select("B11"),
    "S2": img.select("B12")
  }
).rename("NMDI");

// 4. Visualization
var vis = {
  min: -1,
  max: 1,
  palette: [
    "#7f0000", "#d73027", "#fdae61",
    "#ffffbf", "#a6d96a", "#1a9850"
  ]
};

Map.addLayer(nmdi, vis, "NMDI (Drought Index)");

// 5. Optional drought mask (e.g. NMDI < 0)
var drought = nmdi.lt(0).selfMask();
Map.addLayer(drought, {palette:["#d73027"]}, "Drought (NMDI < 0)", false);

// 6. Export NMDI
Export.image.toDrive({
  image: nmdi,
  description: "NMDI_export",
  fileNamePrefix: "NMDI_S2_2023",
  region: roi,
  scale: 20,
  crs: "EPSG:4326",
  maxPixels: 1e13
});